package com.ydlclass.discovery.impl;

import ch.qos.logback.core.joran.util.beans.BeanUtil;
import com.ydlclass.Constant;
import com.ydlclass.ServiceConfig;
import com.ydlclass.YrpcBootstrap;
import com.ydlclass.discovery.AbstractRegistry;
import com.ydlclass.exceptions.DiscoveryException;
import com.ydlclass.exceptions.NetworkException;
import com.ydlclass.utils.NetUtils;
import com.ydlclass.utils.zookeeper.ZookeeperNode;
import com.ydlclass.utils.zookeeper.ZookeeperUtil;
import com.ydlclass.watch.UpAndDownWatcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Knife
 */
@Slf4j
public class ZookeeperRegistry extends AbstractRegistry {

    /**
     * 维护一个zk实例
     */
    private ZooKeeper zooKeeper ;

    public ZookeeperRegistry() {
        this.zooKeeper = ZookeeperUtil.creatZookeeper();
    }

    public ZookeeperRegistry(String connectString,int timeout) {
        this.zooKeeper = ZookeeperUtil.creatZookeeper(connectString,timeout);
    }

    @Override
    public void register(ServiceConfig<?> service) {
        // 服务名称的节点 持久节点
        String parentNode = Constant.BASE_PROVIDERS_PATH + "/" +service.getInterfaceProvider().getName();

        if (!ZookeeperUtil.exists(zooKeeper,parentNode,null)){
            // 不存在，创建一个节点
            ZookeeperNode zookeeperNode = new ZookeeperNode(parentNode,null);
            ZookeeperUtil.creatNode(zooKeeper,zookeeperNode,null, CreateMode.PERSISTENT);
        }

        // 创建本机的临时节点, ip:port ,  服务提供方的端口一般自己设定，需要有一个获取ip的方法
        // ip 我们通常是需要一个局域网ip，不是127.0.0.1，也不是ipv6
        // 比如192.168.10.121；
        //todo: 后续处理端口的问题
        String node = parentNode + "/" + NetUtils.getIp() +":"+ YrpcBootstrap.PORT;
        if (!ZookeeperUtil.exists(zooKeeper,node,null)){
            // 不存在，创建一个节点
            ZookeeperNode zookeeperNode = new ZookeeperNode(node,null);
            ZookeeperUtil.creatNode(zooKeeper,zookeeperNode,null, CreateMode.EPHEMERAL);
        }


        if (log.isDebugEnabled()){
            log.debug("服务，{}被注册",service);
        }
    }

    /**
     * 注册中心的核心目的是什么? 拉取合适的服务列表
     * @param ServiceName 服务的名称
     * @return 服务列表
     */
    @Override
    public List<InetSocketAddress> lookup(String ServiceName) {
        // 1、找到服务对应的节点
        String serviceNode = Constant.BASE_PROVIDERS_PATH + "/" + ServiceName;
        // 2、从zk中获取子节点, 192.168.123:1232;
        List<String> children = ZookeeperUtil.getChildren(zooKeeper, serviceNode, new UpAndDownWatcher());
        // 3、获取了所有的可用的服务列表
        List<InetSocketAddress> inetSocketAddressesList = children.stream().map(ipString -> {
            String[] ipAndPort = ipString.split(":");
            String ip = ipAndPort[0];
            int port = Integer.valueOf(ipAndPort[1]);
            return new InetSocketAddress(ip, port);
        }).collect(Collectors.toList());
        // 一个可用的节点都没有的
        if (inetSocketAddressesList.isEmpty()){
            throw new DiscoveryException("未发现任何可用的服务主机");
        }

        return inetSocketAddressesList;
    }
}
